package com.ayf.payment.game.api.channel.wanxiang;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.channel.BaseHandler;
import com.ayf.payment.game.api.dto.platform.SubstitutePayConfigDTO;
import com.ayf.payment.game.api.dto.platform.pay.WanXiangPayConfigParamVO;
import com.ayf.payment.game.api.httpclient.HttpUtils;
import com.ayf.payment.game.api.service.platform.SubstitutePayConfigService;
import com.ayf.payment.game.api.type.MerchantPayOrderStatusEnum;
import com.ayf.payment.game.api.utils.MD5Util;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.net.SocketTimeoutException;
import java.text.MessageFormat;
import java.util.Map;

@Component
public class WanXPayHandler implements BaseHandler {


    public static final String PAY_ORDER_CREATE = "/pay/apply";

    public static final String PAY_ORDER_QUERY = "/pay/query";

    public static final String PAY_BALANCE_QUERY = "/pay/balance";

    @Autowired
    private SubstitutePayConfigService substitutePayConfigService;

    @Override
    public JSONObject orderCreate(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo", merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());

        String traceId = inputParam.getString("traceId");

        BigDecimal amount = inputParam.getBigDecimal("amount");
        Integer accounttype=0;// 收款账号类别，0：对私，1：对公
        String username = inputParam.getString("account_name");
        String bankName = inputParam.getString("bank_name");
        String banktype = getBankType(traceId, bankName);
        String bankno = inputParam.getString("account_no");

        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String notifyurl = wanXiangPayConfigParamVO.getNotifyurl();
        String key = wanXiangPayConfigParamVO.getKey();


        String sign = getOrderCreateSign(parter, merchantOrderNo, amount, accounttype, username, banktype, bankno, notifyurl, key);
        String url = getOrderCreateUrl(website, parter, merchantOrderNo, amount, accounttype, username, banktype, bankno, notifyurl, sign);
        try {
            Map<String, String> map = HttpUtils.doGet(traceId, url);
            if (map.get(HttpUtils.RESPONSE_CODE).equals("200")) {
                JSONObject jsonDate = JSONObject.parseObject(map.get(HttpUtils.RESPONSE_DATA));
                // code：状态码 0：接收失败,1:接收成功
                String code = jsonDate.getString("code");
                String msg = jsonDate.getString("Msg");
                // Status：付款状态码，1:付款中，2：付款成功，3：付款失败
                // 如果：code为1，Status为2 视为付款成功(直接成功的不再异步通知状态)
                String Status = jsonDate.getString("Status");
                if ("1".equals(code) && "2".equals(Status)) {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_SUCCESS.getStatus());
                } else if ("1".equals(code) && "1".equals(Status)) {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                } else {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                    resJson.put("failReason", msg);
                }
            } else {
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                resJson.put("failReason", "接口请求成功，返回失败，请稍后重试");
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("{} 万象代付下单 通道响应超时 商户订单号:{}", traceId, merchantOrderNo);
        } catch (Exception e) {
            LogPortal.error("{} 万象代付下单失败，发生{}异常 商户订单号:{}", traceId, e.getClass().getName(), merchantOrderNo);
            resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
            resJson.put("failReason", "接口请求失败，请稍后重试");
            return resJson;
        }
        LogPortal.info("{} 万象代付下单 商户订单号:{} 响应报文:{}", traceId, merchantOrderNo, resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject orderQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo", merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());

        String traceId = inputParam.getString("traceId");

        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String key = wanXiangPayConfigParamVO.getKey();

        String sign = getOrderQuerySign(parter, merchantOrderNo, key);
        String url = getOrderQueryUrl(website, parter, merchantOrderNo, sign);
        try {
            LogPortal.info("{} 万象代付下单查询请求参数:{}", traceId, url);
            Map<String, String> map = HttpUtils.doGet(traceId, url);
            if (map.get(HttpUtils.RESPONSE_CODE).equals("200")) {
                JSONObject jsonDate = JSONObject.parseObject(map.get(HttpUtils.RESPONSE_DATA));
                // code：状态码 0：接收失败,1:接收成功
                String code = jsonDate.getString("code");
                // Status：付款状态码，1:付款中，2：付款成功，3：付款失败
                String status = jsonDate.getString("Status");
                if ("1".equals(code)) {
                    if ("1".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                    } else if ("2".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_SUCCESS.getStatus());
                    } else if ("3".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                    }
                } else {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                }
            } else {
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                resJson.put("failReason", "支付通道系统繁忙，请稍后重试");
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("{} 万象代付下单查询 通道响应超时 商户订单号:{}", traceId, merchantOrderNo);
        } catch (Exception e) {
            LogPortal.error("{} 万象代付下单查询失败，发生{}异常 商户订单号:{}", traceId, e.getClass().getName(), merchantOrderNo);
        }
        LogPortal.info("{} 万象代付下单查询 商户订单号:{} 响应报文:{}", traceId, merchantOrderNo, resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject balanceQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        resJson.put("status", "0");
        String traceId = inputParam.getString("traceId");
        String bankName = inputParam.getString("bankName");
        String bankType = getBankType(traceId, bankName);
        if (StringUtils.isEmpty(bankType)) {
            resJson.put("status", "2");
            return resJson;
        }
        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String key = wanXiangPayConfigParamVO.getKey();

        String sign = getBalanceQuerySign(parter, key);
        String url = getBalanceQueryUrl(website, parter, sign);
        try {
            LogPortal.info("{} 万象平台余额查询请求参数:[version=2.1,parter={},encodetype=MD5,sign={}]", traceId, parter, sign);
            Map<String, String> map = HttpUtils.doGet(traceId, url);
            if (map.get(HttpUtils.RESPONSE_CODE).equals("200")) {
                JSONObject jsonDate = JSONObject.parseObject(map.get(HttpUtils.RESPONSE_DATA));
                String code = jsonDate.getString("code");
                String msg = jsonDate.getString("Msg");

                if ("1".equals(code)) { // 业务处理成功
                    String balance = jsonDate.getString("Balance");
                    resJson.put("status", "1");
                    resJson.put("balance", balance);
                } else {
                    LogPortal.error("[{}]万象代付账户余额查询查询-支付通道处理失败code[{}],msg[{}]", traceId, code, msg);
                }
            } else {
                LogPortal.error("[{}]万象代付账户余额查询查询-支付通道系统繁忙，请稍后重试", traceId);
            }
        } catch (SocketTimeoutException e) {
            LogPortal.error("[{}]万象代付账户余额查询查询-通道响应超时,渠道ID[{}],渠道商户号[{}]", substitutePayConfigId, parter);
        } catch (Exception e) {
            LogPortal.error("[{}]万象代付账户余额查询查询失败,发生{}异常,渠道ID[{}],渠道商户号[{}]", traceId, e.getClass().getName(),
                    substitutePayConfigId, parter);
        }
        LogPortal.info("[{}]万象代付账户余额查询查询-渠道ID[{}],渠道商户号[{}],响应报文[{}]", traceId, substitutePayConfigId, parter,
                resJson.toJSONString());
        return resJson;
    }

    private String getOrderCreateUrl(String uri, String parter, String orderno, BigDecimal amount, Integer accounttype,
                                     String username, String banktype, String bankno, String notifyurl, String sign) {
        String format = "{0}" + PAY_ORDER_CREATE + "?version={1}&parter={2}&orderno={3}&amount={4}&accounttype" +
                "={5}&username={6}&banktype={7}&bankno={8}&notifyurl={9}&encodetype" +
                "={10}&sign={11}";
        return MessageFormat.format(format, uri, "2.1", parter, orderno, amount, accounttype, username, banktype,
                bankno, notifyurl, "MD5", sign);
    }

    private String getOrderCreateSign(String parter, String orderno, BigDecimal amount, Integer accounttype, String username,
                                      String banktype, String bankno, String notifyurl, String key) {
        String format = "version={0}&parter={1}&orderno={2}&amount={3}&accounttype={4}&username" +
                "={5}&banktype={6}&bankno={7}&notifyurl={8}&encodetype={9}&key={10}";
        String sign = MessageFormat.format(format, "2.1", parter, orderno, amount, accounttype, username, banktype,
                bankno, notifyurl, "MD5", key);
        String md5 = MD5Util.strToMd5(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBankType(String traceId, String bankName) {
        if (bankName.contains("农业银行")) {
            return "ABC";
        } else if (bankName.contains("中国银行")) {
            return "BOC";
        } else if (bankName.contains("建设银行")) {
            return "CCB";
        } else if (bankName.contains("交通银行")) {
            return "BCM";
        } else if (bankName.contains("招商银行")) {
            return "CMB";
        } else if (bankName.contains("广东发展银行")) {
            return "GDB";
        } else if (bankName.contains("中信银行")) {
            return "CNCB";
        } else if (bankName.contains("民生银行")) {
            return "CMBC";
        } else if (bankName.contains("光大银行")) {
            return "CEB";
        } else if (bankName.contains("平安银行")) {
            return "PAB";
        } else if (bankName.contains("浦发银行")||bankName.contains("浦东发展")) {
            return "SPDB";
        } else if (bankName.contains("邮政储蓄")) {
            return "PSBC";
        } else if (bankName.contains("华夏银行")) {
            return "HXB";
        } else if (bankName.contains("兴业银行")) {
            return "CIB";
        }else if (bankName.contains("工商银行")) {
            return "ICBC";
        } else {
            LogPortal.error("[{}]万象代付银行类别错误[{}]", traceId, bankName);
            return null;
        }
    }

    private String getOrderQueryUrl(String uri, String parter, String orderno, String sign) {
        String format = "{0}" + PAY_ORDER_QUERY + "?version={1}&parter={2}&orderno={3}&encodetype={4}&sign={5}";
        return MessageFormat.format(format, uri, "2.1", parter, orderno, "MD5", sign);
    }

    private String getOrderQuerySign(String parter, String orderno, String key) {
        String format = "version={0}&parter={1}&orderno={2}&encodetype={3}&key={4}";
        String sign = MessageFormat.format(format, "2.1", parter, orderno, "MD5", key);
        String md5 = MD5Util.strToMd5(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBalanceQuerySign(String parter, String key) {
        String format = "version={0}&parter={1}&encodetype={2}&key={3}";
        String sign = MessageFormat.format(format, "2.1", parter, "MD5", key);
        String md5 = MD5Util.strToMd5(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBalanceQueryUrl(String uri, String parter, String sign) {
        String format = "{0}" + PAY_BALANCE_QUERY + "?version={1}&parter={2}&encodetype={3}&sign={4}";
        return MessageFormat.format(format, uri, "2.1", parter, "MD5", sign);
    }
}
